from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import ListView
from django.contrib.auth.decorators import login_required
from notifications.signals import notify
from django.core.cache import cache

from user.models import User, LimitLike, UserFollow
from .models import PostList, PostCategory
from .forms import PublishForm
from trend.models import TrendList
from comment.models import PostComment
from comment.forms import PostCommentForm


# Create your views here.

class postListView(ListView):

    def __init__(self):
        super(postListView).__init__()
        self.model = PostList
        self.template_name = 'post/post_list.html'
        self.context_object_name = 'post_list'
        self.paginate_by = 4

    def get_queryset(self):
        post_list = cache.get('post_list')

        if not post_list:
            post_list = super(postListView, self).get_queryset().all()
            cache.set('post_list', post_list)
        return post_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        paginator = context.get('paginator')
        page = context.get('page_obj')
        is_paginated = context.get('is_paginated')
        pagination_data = self.pagination_data(paginator, page, is_paginated)

        recent_list = PostList.objects.all().order_by('-publish_time')[:5]
        context['recent_list'] = recent_list

        context.update(pagination_data)
        return context

    def pagination_data(self, paginator, page, is_paginated):
        """
        分页
        """
        if not is_paginated:
            return {}
        left = []
        right = []
        left_has_more = False
        right_has_more = False
        first = False
        last = False
        page_number = page.number
        total_pages = paginator.num_pages
        page_range = paginator.page_range

        if page_number == 1:
            right = page_range[page_number:page_number + 4]

            if right[-1] < total_pages - 1:
                right_has_more = True
            if right[-1] < total_pages:
                last = True

        elif page_number == total_pages:
            left = page_range[(page_number - 5) if (page_number - 5) > 0 else 0:page_number - 1]
            if left[0] > 2:
                left_has_more = True
            if left[0] > 1:
                first = True

        else:
            left = page_range[(page_number - 5) if (page_number - 5) > 0 else 0:page_number - 1]
            right = page_range[page_number:page_number + 2]

            if right[-1] < total_pages - 1:
                right_has_more = True
            if right[-1] < total_pages:
                last = True

            if left[0] > 2:
                left_has_more = True
            if left[0] > 1:
                first = True

        data = {
            'left': left,
            'right': right,
            'left_has_more': left_has_more,
            'right_has_more': right_has_more,
            'first': first,
            'last': last,
        }

        return data


class postCategoryView(ListView):

    def __init__(self):
        super(postCategoryView).__init__()
        self.model = PostList
        self.template_name = 'post/post_category.html'
        self.context_object_name = 'post_list'
        self.paginate_by = 4

    def get_queryset(self):
        c_id = get_object_or_404(PostCategory, pk=self.kwargs.get('pk'))
        post_list = cache.get('post_list_{}'.format(c_id))

        if not post_list:
            post_list = super(postCategoryView,self).get_queryset().filter(category=c_id)
            cache.set('post_list_{}'.format(c_id), post_list)
        return post_list

    def get_context_data(self, **kwargs):
        """
        """
        context = super(postCategoryView, self).get_context_data(**kwargs)
        c_id = get_object_or_404(PostCategory, pk=self.kwargs.get('pk'))
        paginator = context.get('paginator')
        page = context.get('page_obj')
        is_paginated = context.get('is_paginated')
        pagination_data = self.pagination_data(paginator, page, is_paginated)

        recent_list = PostList.objects.all().order_by('-publish_time')[:5]
        context['recent_list'] = recent_list
        context['c_id'] = c_id
        context.update(pagination_data)

        return context

    def pagination_data(self, paginator, page, is_paginated):
        if not is_paginated:
            return {}
        left = []
        right = []
        left_has_more = False
        right_has_more = False
        first = False
        last = False
        page_number = page.number
        total_pages = paginator.num_pages
        page_range = paginator.page_range

        if page_number == 1:
            right = page_range[page_number:page_number + 4]

            if right[-1] < total_pages - 1:
                right_has_more = True
            if right[-1] < total_pages:
                last = True

        elif page_number == total_pages:
            left = page_range[(page_number - 5) if (page_number - 5) > 0 else 0:page_number - 1]
            if left[0] > 2:
                left_has_more = True
            if left[0] > 1:
                first = True

        else:
            left = page_range[(page_number - 5) if (page_number - 5) > 0 else 0:page_number - 1]
            right = page_range[page_number:page_number + 2]

            if right[-1] < total_pages - 1:
                right_has_more = True
            if right[-1] < total_pages:
                last = True

            if left[0] > 2:
                left_has_more = True
            if left[0] > 1:
                first = True

        data = {
            'left': left,
            'right': right,
            'left_has_more': left_has_more,
            'right_has_more': right_has_more,
            'first': first,
            'last': last,
        }

        return data


@login_required
def post_publish(request):
    """
    主题帖发布视图
    """
    # 获取next值用作重定向跳转，next值为post_list页面url
    redirect_to = request.POST.get('next', request.GET.get('next', ''))

    if request.method == 'POST':
        form = PublishForm(request.POST, request.user)
        if form.is_valid():

            form.instance.user = request.user
            form.save()

            # 增加到个人动态
            trend_content = '发布了主题《%s》'%form.cleaned_data['title']
            trend = TrendList.objects.create(user=request.user, content=trend_content)
            trend.save()

            # 通知粉丝该用户上传了新的音乐
            fans_id = list(map(lambda x: x['fan_id'], UserFollow.objects.
                               filter(follow=request.user).values('fan_id')))
            recipient = User.objects.filter(id__in=fans_id)
            if recipient:
                notify.send(request.user, recipient=recipient,verb='{}发布了主题《{}》'.
                            format(request.user.user, form.cleaned_data['title']))

            if redirect_to:
                return redirect(redirect_to)
            else:
                return redirect('post:post')

    else:
        form = PublishForm()

    return render(request, 'post/post_publish.html', context={'form': form})


def post_detail(request, pk):
    post = get_object_or_404(PostList, id=pk)
    recent_list = PostList.objects.all().order_by('-publish_time')[:5]
    comment_list = PostComment.objects.filter(post=post)

    form = PostCommentForm()
    context = {'post': post,
               'comment_list' :comment_list,
               'recent_list': recent_list,
               'form': form}

    return render(request, 'post/post_detail.html', context=context)


@csrf_exempt
def post_like(request):
    """
    主题帖点赞
    """
    if request.method == 'POST':
        post_id = request.POST.get('post_id', '')
        user_id = request.POST.get('user_id', '')
        user = User.objects.get(id=user_id)
        post = PostList.objects.get(id=post_id)

        _like_count = post.like_count
        like_limit = LimitLike.objects.filter(user_id=user_id, post_id=post_id)
        if like_limit:
            return JsonResponse({'status': 'warning', 'like_count': _like_count})

        LimitLike.objects.create(user=user, post=post)
        post.like_count = _like_count + 1
        post.update()
        like_count  = post.like_count
        notify.send(user, recipient=post.user, target=post,
                    verb='{}赞了你的主题'.format(user.username))

        trend = TrendList.objects.create(user=user, content='对主题《{}》点赞成功'.format(post.title))
        trend.save()
        return JsonResponse({'status': 'ok', 'like_count': like_count})

